/*
 * Target.cc
 *
 *  Created on: Sep 22, 2012
 *      Author: HUNG
 */

#include "Target.h"
#include "Bastation.h"

Define_Module(Target);

void Target::initialize()
{
    this->typeTrajectory = getParentModule()->par("typeTrajectory");
    this->X_MAX = par("X_MAX");
    this->Y_MAX = par("Y_MAX");
    remove("data/Trajectorytrue.txt");
    if(this->typeTrajectory == 0)
    {
        //Read positions of object to array
        ev <<" Read positions of object to array \n";
        char str[100];
        char *result    = NULL;
        char *temp      = new char[1024];
        FILE *infile    = NULL;
        infile          = fopen(par("FILE_OBJ_MOV"), "r");

        pos_index = 0;
        while(!feof(infile))
        {
            fgets(str, 100, infile);
            if(strlen(str) <= 3 || strchr(str, ' ') == NULL) break;
            result = strtok(str, " ");
            strcpy(temp, result);
            X[pos_index] = atoi(temp);
            result = strtok(NULL, " ");
            strcpy(temp, result);
            Y[pos_index] = atoi(temp);
            pos_index++;
            if(pos_index >= 5000)
            {
                printf("Positions are too big !!\n");
                break;
            }
        }
        fclose(infile);
        this->xpos = X[0];
        this->ypos = Y[0];
    }
    else if(this->typeTrajectory == 1)
    {
        remove("data/Trajectory-dynamic.txt");
        this->xpos          = 300;//rand() % ((int)X_MAX - 20) + 10;
        this->ypos          = 250;//rand() % ((int)Y_MAX - 20) + 10;
    }
    this->setPosition(xpos, ypos);
    this->heading       = 360 * dblrand();
    this->pos_num       = pos_index;
    this->pos_index     = 0;
    this->numSSProcess  = 0;
    this->ssRange       = getParentModule()->par("ssRange");
    this->timeStep      = getParentModule()->par("TimeStep");
    this->speed         = getParentModule()->par("targetSpeed");

    //Thay doi timeStep
    if(timeStep == 0.3333) step = 1;
    else if(timeStep == 0.6667) step = 2;
    else if(timeStep == 1) step = 3;

    //Thay doi van toc
//    if(speed == 5) step = 1;
//    else if(speed == 10) step = 2;
//    else if(speed == 15) step = 3;

    //schedule the first event
    cMessage *msg = new cMessage("OBJECT_TIMER");
    msg->setKind(M_SELF_T1);
    scheduleAt(simTime() + 1000, msg);
}

void Target::handleMessage(cMessage *msg)
{
    if(strcmp(msg->getName(), "OBJECT_TIMER") == 0)
    {
        Bastation *bs = (Bastation *) simulation.getModule(simulation.getLastModuleId());
        if(this->typeTrajectory == 0)
        {
            xpos = X[pos_index];
            ypos = Y[pos_index];
            if(xpos > X_MAX || ypos > Y_MAX) endSimulation();

            Sensor *s;
            for(int i = 0; i < numSSProcess; i++)
            {
                s = (Sensor *)simulation.getModule(sensorIDProcess[i]);
                s->resetDisplay();
            }

            FILE *file = fopen("data/Trajectorytrue.txt", "a");
            fprintf(file,"%f %f %f\n", xpos, ypos, simTime().dbl());
            fclose(file);

            this->setPosition(xpos, ypos);
            bs->t_start         = simTime();
            this->startEvent();
            scheduleAt(simTime() + timeStep, msg);

            this->numSSProcess  = 0;
            pos_index           += step;
            if(pos_index >= pos_num - 1)
            {
                endSimulation();
            }
        }
        else
        {
            heading += 120 * (dblrand() - 0.5) * timeStep;

            heading = fmod(heading + 360, 360);

            double vx = sin(heading * M_PI / 180) * speed;
            double vy = -cos(heading * M_PI / 180) * speed;

            xpos += vx * timeStep;
            ypos += vy * timeStep;

            if(xpos < 5)
            {
                xpos = 5; heading = 360 - heading;
            }

            if(xpos > X_MAX - 5)
            {
                xpos = X_MAX - 5; heading = 360 - heading;
            }

            if(ypos < 5)
            {
                ypos = 5; heading = 180 - heading;
            }

            if(ypos > Y_MAX - 5)
            {
                ypos = Y_MAX - 5; heading = 180 - heading;
            }


            FILE *f = fopen("data/Trajectory-dynamic.txt", "a");
            fprintf(f, "%f %f\n", xpos, ypos);
            fclose(f);

            Sensor *s;
            for(int i = 0; i < numSSProcess; i++)
            {
                s = (Sensor *)simulation.getModule(sensorIDProcess[i]);
                s->resetDisplay();
            }
            this->setPosition(xpos, ypos);

            this->startEvent();
            bs->t_start = simTime();

            scheduleAt(simTime() + timeStep, msg);
            this->numSSProcess = 0;

            //if(pos_index > 5000) endSimulation();
        }
    }
}

void Target::startEvent()
{
    Enter_Method_Silent("startEvent()");
    Sensor *s;
    double xlength, ylength, distance;
    total = 0;

    //duyet tat ca cac nut sensor
    for(int i = NUMTARGET + 2; i < simulation.getLastModuleId(); i++)
    {
        s = (Sensor *)simulation.getModule(i);
        if(s->energy < 10.0)
        {
            s->setDisplay("black");
            s->isDead = true;
            continue;
        }


        xlength = (double)(s->xpos - xpos);
        ylength = (double)(s->ypos - ypos);
        distance = sqrt(xlength * xlength + ylength * ylength);

        if(distance <= ssRange)
        {
            ev <<"\n Cluster: "<<s->getId() - 3;
            this->cluster[total] = s;
            total++;
        }
    }

    if(total >= 1)
    {
        ev << "\n Start Event";
        this->getDisplayString().setTagArg("r", 0, ssRange);
        this->getDisplayString().setTagArg("r", 1, "white");
        this->getDisplayString().setTagArg("r", 2, "red");

        ev <<"\n So luong sensor tham gia su kien: " <<total;
        for(int i = 0; i < total; i++)
        {
            s = this->cluster[i];
            if(s->energy >= 10)
            {
                //                s->active = true;
                //                s->setDisplay("green");
                s->sendEventNotifyMessage(total);
            }
        }

    }
    else
    {
        this->getDisplayString().setTagArg("r", 0, "0");
    }
}

void Target::storeID(int id)
{
    int count = 0;
    for(int i = 0; i < numSSProcess; i++)
    {
        if(id == sensorIDProcess[i])
        {
            count++;
            break;
        }
    }

    if(count == 0)
    {
        this->sensorIDProcess[numSSProcess] = id;
        this->numSSProcess++;
    }
}

void Target::setPosition(double x, double y)
{
    getDisplayString().setTagArg("p", 0, x);
    getDisplayString().setTagArg("p", 1, y);
}
